use std::{fmt::Display, path::Path};

pub fn to_list<T: Display>(path: T) -> Vec<String> {
    format!("{}", path)
        .replace("\\\\", "/")
        .replace("\\", "/")
        .split("/")
        .map(|s| s.to_owned())
        .collect()
}

use path_absolutize::*;

pub trait PathDisp {
    fn to_list(&self) -> Vec<String>;
    fn disp(&self) -> String;
    fn disp_by(&self, sep: &str) -> String;
    fn abs(&self) -> String;
    fn resolve(&self, path: &str) -> String;
}

impl PathDisp for Path {
    fn resolve(&self, path: &str) -> String {
        std::path::Path::new(&format!("{}/{}", self.disp(), Self::new(path).disp()))
            .absolutize()
            .unwrap()
            .to_str()
            .unwrap()
            .to_string()
    }

    fn to_list(&self) -> Vec<String> {
        to_list(self.to_str().unwrap().to_string())
    }

    fn disp_by(&self, sep: &str) -> String {
        self.to_list().join(sep)
    }

    fn disp(&self) -> String {
        self.disp_by("/")
    }

    fn abs(&self) -> String {
        self.resolve("")
    }
}

#[cfg(test)]
mod test {
    use crate::*;
    use std::path::Path;

    #[test]
    fn test() {
        let path = Path::new("./src");
        println!("{:?}", path.resolve("../a/b/../c"));
    }
}
